/*
 * @brief 温湿度传感器
 */

#include <rtthread.h>
#include <rtdevice.h>

#include <sensor_htu21d.h>

#define DBG_TAG "htu21d.c"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

static struct rt_i2c_bus_device *i2c_bus = RT_NULL;
float tempVal = 0.0f, humiVal = 0.0f;

/**
 * @brief  向I2C从设备寄存器中写数据
 * @param  *bus -> I2C设备对象句柄
 * @param  reg -> 寄存器
 * @param  *data -> 数据
 * @return 是否写入成功
 */
static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t *data)
{
    rt_uint8_t buf[4] = { 0 };
    struct rt_i2c_msg msgs;
    buf[0] = reg;
    msgs.addr = HTU21D_ADDR;
    msgs.flags = RT_I2C_WR;
    msgs.buf = buf;
    msgs.len = 1;
    if (rt_i2c_transfer(bus, &msgs, 1) == 1)
        return RT_EOK;
    else
        return -RT_ERROR;
}

/**
 * @brief  读取I2C从设备寄存器数据
 * @param  *bus -> I2C设备对象句柄
 * @param  len -> 读取数据长度
 * @param  *buf -> 读取数据
 * @return 是否读取成功
 */
static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf)
{
    struct rt_i2c_msg msgs;
    msgs.addr = HTU21D_ADDR;
    msgs.flags = RT_I2C_RD;
    msgs.buf = buf;
    msgs.len = len;
    if (rt_i2c_transfer(bus, &msgs, 1) == 1)
        return RT_EOK;
    else
        return -RT_ERROR;
}

/**
 * @brief  读取温度值
 * @param  无
 * @return 温度值
 */
float hut21d_read_temp(void)
{
    rt_uint8_t temp[2] = { 0 };
    write_reg(i2c_bus, HTU21D_READ_TEMP, 0);
    rt_thread_mdelay(50);
    read_regs(i2c_bus, 2, temp);
    if ((temp[1] & 0x02) == 0)
    {
        tempVal = -46.85f + 175.72f * ((temp[0] << 8 | temp[1]) & 0xfffc) / (1 << 16);
        return tempVal;
    }
    return -1;
}

/**
 * @brief  读取湿度值
 * @param  无
 * @return 湿度值
 */
float hut21d_read_humi(void)
{
    rt_uint8_t temp[2] = { 0 };
    write_reg(i2c_bus, HTU21D_READ_HUMI, 0);
    rt_thread_mdelay(50);
    read_regs(i2c_bus, 2, temp);
    if ((temp[1] & 0x02) == 0x02)
    {
        humiVal = -6 + 125 * ((temp[0] << 8 | temp[1]) & 0xfffc) / (1 << 16);
        return humiVal;
    }
    return -1;
}

/**
 * @brief  HTU21D初始化
 * @param  无
 * @return 初始化是否成功
 */
int htu21d_init(void)
{
    i2c_bus = (struct rt_i2c_bus_device *) rt_device_find(HTU21D_I2C_BUS_NAME);
    if (i2c_bus == RT_NULL)
    {
        rt_kprintf("failed to find %s device!\n", HTU21D_I2C_BUS_NAME);
        return -1;
    }
    write_reg(i2c_bus, HTU21D_RESET, 0);
    rt_thread_mdelay(50);
    return 0;
}
